<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="css-parse.html">

<script>

  Polymer.StyleUtil = (function() {

    return {

      MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css]',

      toCssText: function(rules, callback, preserveProperties) {
        if (typeof rules === 'string') {
          rules = this.parser.parse(rules);
        } 
        if (callback) {
          this.forEachStyleRule(rules, callback);
        }
        return this.parser.stringify(rules, preserveProperties);
      },

      forRulesInStyles: function(styles, callback) {
        for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
          this.forEachStyleRule(this.rulesForStyle(s), callback);
        }
      },

      rulesForStyle: function(style) {
        if (!style.__cssRules && style.textContent) {
          style.__cssRules =  this.parser.parse(style.textContent);
        }
        return style.__cssRules;
      },

      clearStyleRules: function(style) {
        style.__cssRules = null;
      },

      forEachStyleRule: function(node, callback) {
        var s = node.selector;
        var skipRules = false;
        if (node.type === this.ruleTypes.STYLE_RULE) {
          callback(node);
        } else if (node.type === this.ruleTypes.KEYFRAMES_RULE || 
            node.type === this.ruleTypes.MIXIN_RULE) {
          skipRules = true;
        }
        var r$ = node.rules;
        if (r$ && !skipRules) {
          for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) {
            this.forEachStyleRule(r, callback);
          }
        }
      },

      // add a string of cssText to the document.
      applyCss: function(cssText, moniker, target, afterNode) {
        var style = document.createElement('style');
        if (moniker) {
          style.setAttribute('scope', moniker);
        }
        style.textContent = cssText;
        target = target || document.head;
        if (!afterNode) {
          var n$ = target.querySelectorAll('style[scope]');
          afterNode = n$[n$.length-1];
        } 
        target.insertBefore(style, 
          (afterNode && afterNode.nextSibling) || target.firstChild);
        return style;
      },

      // returns cssText of styles in a given module; also un-applies any
      // styles that apply to the document.
      cssFromModule: function(moduleId) {
        var m = Polymer.DomModule.import(moduleId);
        if (m && !m._cssText) {
          var cssText = '';
          var e$ = Array.prototype.slice.call(
            m.querySelectorAll(this.MODULE_STYLES_SELECTOR));
          for (var i=0, e; i < e$.length; i++) {
            e = e$[i];
            // style elements inside dom-modules will apply to the main document
            // we don't want this, so we remove them here.
            if (e.localName === 'style') {
              // get style element applied to main doc via HTMLImports polyfill
              e = e.__appliedElement || e;
              e.parentNode.removeChild(e);
            // it's an import, assume this is a text file of css content.
            } else {
              e = e.import && e.import.body;
            }
            // adjust paths in css.
            if (e) {
              cssText += 
                Polymer.ResolveUrl.resolveCss(e.textContent, e.ownerDocument);
            }
          }
          m._cssText = cssText;
        }
        return m && m._cssText || '';
      },

      parser: Polymer.CssParse,
      ruleTypes: Polymer.CssParse.types

    };

  })();

</script>